﻿#ifndef SWANLINK_FINANCE_CARDSENDER_ADAPTOR_F5G006_LIB_LIBF5G006_INCLUDE_LOGGER_H
#define SWANLINK_FINANCE_CARDSENDER_ADAPTOR_F5G006_LIB_LIBF5G006_INCLUDE_LOGGER_H

#include <cstdint>
#include <string>
#include <queue>
#include "stoppable_thread.h"

enum LogLevel {
    LL_DEBUG = 0,
    LL_INFO,
    LL_ERROR
};


class IAppender {
 public:
    virtual ~IAppender() = default;

    virtual bool start() = 0;
    virtual void append(int level, const std::string& msg) = 0;
};


class ConsoleAppender : public IAppender {
 public:
    ConsoleAppender();
    ~ConsoleAppender();

    bool start() override;
    void append(int level, const std::string& msg) override;
};


class FileAppender : public IAppender {
 public:
    FileAppender(const char* logsDir, const char* fileNamePrefix);
    ~FileAppender();

    bool start() override;
    void append(int level, const std::string& msg) override;

 private:
    void writeThreadFunc();

    bool openFile(const std::string& filePath);
    void closeCurrentFile();

 private:
    std::string m_logsDir;            // 日志目录
    std::string m_fileNamePrefix;    // 日志文件名前缀
    std::string m_currentFilePath;    // 当前日志文件路径
    FILE* m_stream;                // 日志文件流
    StoppableThread m_writeThread;    // 写线程对象
    bool m_writable;
    std::queue<std::string> m_msgQue;
    std::mutex m_queMutex;
};


class Logger {
 public:
    Logger();
    ~Logger();

    friend inline Logger& globalLogger();

    void setCurrentLevel(int level);
    bool isLoggable(int level);

    bool enableFileLog(const char* logsDir, const char* fileNamePrefix);
    void disableFileLog();

    bool enableConsoleLog();
    void disableConsoleLog();

    void writeln(int level, const char* fmt, ...);

 private:
    static Logger _instance;
    ConsoleAppender* m_consoleAppender;
    FileAppender* m_fileAppender;
    int m_currentLevel;
    std::mutex m_mutex;
};

inline Logger& globalLogger() { return Logger::_instance; }

#endif // SWANLINK_FINANCE_CARDSENDER_ADAPTOR_F5G006_LIB_LIBF5G006_INCLUDE_LOGGER_H
